#!/usr/bin/env python
# -*- coding: utf-8 -*-

# @Author  : linlvfei2008@126.com
# @Time    : 2019/7/24 00:02
# @Site    : https://gitee.com/chunhuayuyun
import re
import os
from datetime import datetime

import unittest

import common.HTMLTestRunner_v2 as HTMLTestRunner


class RunTest:

    def __init__(self):
        self.project_path = os.path.split(os.path.realpath(__file__))[0]
        # 指定Case文件
        self.case_list_file = os.path.join(self.project_path, "case_list.ini")
        self.case_list = []

    @classmethod
    def get_all_files(cls, dir_name):
        """
        查找目录下的所有文件方法
        :param dir_name: 相对路径或者绝对路径
        :return: 所有可以执行的用例
        """
        case_list = []
        list_dir = os.listdir(dir_name)
        for i in range(0, len(list_dir)):
            path = os.path.join(dir_name, list_dir[i])
            if os.path.isdir(path):
                case_list.extend(cls.get_all_files(path))
            if os.path.isfile(path):
                file_name = re.split(r'[/\\]', path)[-1]
                if path.endswith('.pyc') or path.endswith('__init__.py') or not file_name.startswith('test_'):
                    # 排除的文件.pyc  __init__.py  必须是‘test_’开头
                    pass
                else:
                    case_list.append(path.replace("\\", '/'))
        return case_list

    def set_case_list(self):
        """
        组装所有测试用例变成一个列表路径
        :return: 测试用例列表
        """
        fb = open(self.case_list_file, encoding='utf-8')
        for data in fb.readlines():
            data = str(data).replace("\n", "")
            # 如果以分号开头视为无效测试用例
            if data != '' and not data.startswith(";"):
                # 如果是.PY文件结尾视为测试用例直接保留
                if data.endswith('.py'):
                    self.case_list.append(data)
                else:
                    # 如果是目录则获得所有测试用例
                    t_list = self.get_all_files(data)
                    for case in t_list:
                        self.case_list.append(case)
        fb.close()

        # 将删除测试用例后移动
        for case in self.case_list:
            if 'delete' in str(case):
                self.case_list.append(case)
                self.case_list.remove(case)

        print('找到 %d 条测试用例' % len(self.case_list))

    def set_case_suite(self):
        """
        装载测试用例
        :return:
        """

        self.set_case_list()

        test_suite = unittest.TestSuite()
        suite_module = []
        for case in self.case_list:
            case_name = case.split("/")[-1]
            case_path = str(case).replace(case_name, '')

            # pattern='test*.py' 规定测试集文件开头命名为test，也可以是pattern='test_*.py'
            discover = unittest.defaultTestLoader.discover(start_dir=case_path,
                                                           pattern=case_name,
                                                           top_level_dir=self.project_path)
            suite_module.append(discover)

        if len(suite_module) > 0:
            for suite in suite_module:
                for test_name in suite:
                    test_suite.addTest(test_name)

        else:
            return None
        return test_suite

    def run(self):
        """
        最终执行测试脚本生成测试报告
        :return:
        """
        print('=' * 40 + '测试开始' + '=' * 40)
        fp = open("./result/report/" + str(datetime.now().strftime('%Y%m%d%H%M%S')) + '.html', 'wb')
        try:
            suit = self.set_case_suite()
            if suit is not None:
                runner = HTMLTestRunner.HTMLTestRunner(stream=fp,
                                                       title='Test report',
                                                       description='Automated test report')
                runner.run(suit)
            else:
                print("没有找到测试用例！")

        except Exception as ex:
            print(str(ex))
        finally:
            fp.close()
            print('=' * 40 + '测试结束' + '=' * 40)


if __name__ == '__main__':
    obj = RunTest()
    obj.run()
